import hashlib
import random
import re
from concurrent.futures.thread import ThreadPoolExecutor

import jwt
import qiniu
import requests
from django.conf import settings
from jwt import InvalidTokenError
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.pagination import PageNumberPagination

from polls.models import User
from vote2003 import app
from vote2003.settings import MAX_WORKING_THREADS

USERNAME_PATTERN = re.compile(r'\w{6,20}')
TEL_PATTERN = re.compile(r'1[3-9]\d{9}')


def check_username(username):
    """检查用户名"""
    return USERNAME_PATTERN.fullmatch(username) is not None


def check_password(password):
    """检查用户口令"""
    return len(password) >= 6


def check_tel(tel):
    """检查手机号"""
    return TEL_PATTERN.fullmatch(tel) is not None


def gen_sha256_digest(content):
    """生成SHA256哈希摘要（签名、指纹）"""
    if not isinstance(content, bytes):
        if isinstance(content, str):
            content = content.encode('utf-8')
        else:
            content = bytes(content)
    return hashlib.sha256(content).hexdigest()


def random_code(length=6):
    """生成随机短信验证码"""
    return ''.join(random.choices('0123456789', k=length))


@app.task
def send_mobile_code(tel, code):
    """发送短信验证码"""
    resp = requests.post(
        url='http://sms-api.luosimao.com/v1/send.json',
        auth=('api', 'key-a191efa9e007373daf2c838a98533405'),
        data={
            'mobile': tel,
            'message': f'您的短信验证码是{code}，打死也不能告诉别人哟。【Python小课】'
        },
        verify=False
    )
    return resp.json()


POOL = ThreadPoolExecutor(max_workers=MAX_WORKING_THREADS)

AUTH = qiniu.Auth(
    'KarvlHfUdoG1mZNSfDVS5Vh3nae2jUZumTBHK-PR',
    'SFPFkAn5NENhdCMqMe9wd_lxGHAeFR5caXxPTtt7'
)
BUCKET_NAME = 'myvote2003'


def upload_file_to_qiniu(key, file_path):
    """上传指定路径的文件到七牛云"""
    token = AUTH.upload_token(BUCKET_NAME, key)
    return qiniu.put_file(token, key, file_path)


def upload_stream_to_qiniu(key, stream, size):
    """上传二进制流到七牛云"""
    token = AUTH.upload_token(BUCKET_NAME, key)
    return qiniu.put_stream(token, key, stream, None, size)


# 里氏替换原则（Liskov Substitution Principle）
class LoginRequiredAuthentication(BaseAuthentication):
    """自定义认证类"""

    def authenticate(self, request):
        token = request.META.get('HTTP_TOKEN')
        try:
            payload = jwt.decode(token, settings.SECRET_KEY)
            user = User()
            user.no = payload['userid']
            user.is_authenticated = True
            return user, token
        except InvalidTokenError:
            raise AuthenticationFailed('请提供有效的身份令牌')


class CustomizedPagination(PageNumberPagination):
    # 默认页面大小
    page_size = 5
    # 页面大小对应的查询参数
    page_size_query_param = 'size'
    # 页面大小的最大值
    max_page_size = 50
